package com.shaoyu.tools.event.core;

import com.google.common.eventbus.AsyncEventBus;
import com.google.common.eventbus.SubscriberExceptionHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.PreDestroy;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.locks.LockSupport;

/**
 * @Desc :
 * @Author: shaoyu
 * @Date : 2022/11/2 10:53
 */
public class AsyncFilterEventBus extends AsyncEventBus {

    private final InterceptorRegister interceptorRegister;

    private final ThreadPoolExecutor executorService;

    private long time = 0L;

    private final long intervalTime = 30*1000L;

    private Logger logger = LoggerFactory.getLogger(AsyncFilterEventBus.class);

    public AsyncFilterEventBus(ExecutorService executor, SubscriberExceptionHandler subscriberExceptionHandler) {
        super(executor, subscriberExceptionHandler);
        interceptorRegister = new InterceptorRegister(executor);
        this.executorService = (ThreadPoolExecutor) executor;
        time = System.currentTimeMillis();
        logger.info("init AsyncFilterEventBus success! the core pool size is {},max pool size is {}",executorService.getCorePoolSize(),executorService.getMaximumPoolSize());
    }

    @Override
    public void register(Object object) {
        this.interceptorRegister.registerInterceptor(object);
        super.register(object);
    }


    @Override
    public void unregister(Object listener) {
        this.interceptorRegister.unregisterInterceptor(listener);
        super.unregister(listener);
    }

    @Override
    public void post(Object event) {
        if (this.interceptorRegister.intercepted(event)) {
            return;
        }
        super.post(event);
        monitorExecutorInfo();
    }

    private void monitorExecutorInfo() {
        long currentTimeMillis = System.currentTimeMillis();
        if(currentTimeMillis - time > intervalTime){
            time = currentTimeMillis;
        }
        long completedTaskCount = executorService.getCompletedTaskCount();
        int activeCount = executorService.getActiveCount();
        logger.info("AsyncFilterEventBus ThreadPool Info\r\n \t completedTaskCount: \t {} \r\n \t activeCount: \t {}",completedTaskCount,activeCount);
    }


    @PreDestroy
    public void shutdown(){
        long count = 0;
        //如果有任务执行 给10秒钟缓冲
        while (this.executorService.getActiveCount()>0 && count < 1000){
            LockSupport.parkNanos(10*1000*1000L);
            count++;
        }
        this.executorService.shutdown();
    }
}
